package com.linshengjian.snowball.core;

import com.linshengjian.snowball.core.exception.SystemErrorException;
import com.linshengjian.snowball.utils.ObjectConvertUtils;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

import javax.persistence.MappedSuperclass;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

@Accessors(chain = true)
@Setter
@Getter
@MappedSuperclass
public abstract class BaseEntity<ID extends Serializable, M extends BaseModel<ID>> extends Entity<ID> {

    /**
     * 获取泛型 M 的 class
     * @return
     */
    protected Class<M> getModelClass() {
        Type genType = getClass().getGenericSuperclass();
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

        return (Class) params[1];
    }

    public <TID extends Serializable, TM extends BaseModel<TID>> TM toModel(Class<TM> clazz) throws SystemErrorException {
        try {
            TM model = clazz.newInstance();
            return ObjectConvertUtils.getInstance().assign(model, this, false, true, false);
        } catch (Exception e) {
            e.printStackTrace();
            throw new SystemErrorException(e);
        }
    }

    public M toModel() throws SystemErrorException {
        Class<M> clazz = getModelClass();
        return toModel(clazz);
    }

    public BaseEntity assign(Object obj) throws SystemErrorException {
        try {
            ObjectConvertUtils.getInstance().assign(this, obj, true, false, true);
            return this;
        } catch (Exception e) {
            e.printStackTrace();
            throw new SystemErrorException(e);
        }
    }
    public BaseEntity assign(Object obj, boolean force) throws SystemErrorException {
        try {
            ObjectConvertUtils.getInstance().assign(this, obj, true, force, true);
            return this;
        } catch (Exception e) {
            e.printStackTrace();
            throw new SystemErrorException(e);
        }
    }
}